package com.hnx.admin.aurora.utils;

import lombok.extern.slf4j.Slf4j;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Objects;
import java.util.Optional;

/*
创建人： 倔强的头发
创建时间：2025/6/15
功能描述:

*/
@Slf4j
public class ReflectUtil {
    /*
     * 获取对象属性值(支持继承链和私有属性)
     *  @param target       目标对象
     *  @param fieldName 属性名(支持多级如"obj.sub.name")
     *  @return Optional包装的属性值
     * */
    public static Optional<Object> getFieldNameValue(Object target, String fieldName) {
        if (target == null || !StringUtils.hasText(fieldName)) {
            return Optional.empty();
        }
        try {
            //处理嵌套属性
            if (fieldName.contains(".")) {
                String[] parts = fieldName.split("\\.", 2);
                Object innerObj = getFieldNameValue(target, parts[0]).orElse(null);
                return innerObj != null ? getFieldNameValue(innerObj, parts[1]) : Optional.empty();
            }
            Field field = findFieldRecursively(target.getClass(), fieldName);
            if (null == field) {
                return Optional.empty();
            }
            field.setAccessible(true);
            return Optional.ofNullable(field.get(target));
        } catch (Exception ex) {

        }
        return Optional.empty();
    }
    /*
     * 递归查找类继承链中的属性(含父类)
     * @param clazz       目标类
     * @param fieldName 属性名
     * @return 找到的Field对象(找不到返回null)
     * */
    private static Field findFieldRecursively(Class<?> clazz, String fieldName) {
        for (Class<?> type = clazz; type != Objects.class; type = type.getSuperclass()) {
            try {
                Field field = type.getDeclaredField(fieldName);
                if (!field.isSynthetic()) {//排除编译器生成的合成字段
                    return field;
                }
            } catch (Exception ex) {
                log.error("反射获取字段属性异常：{}", ex.getMessage());
                return null;
            }
        }
        return null;
    }

    /**
     * 获取字段值
     *
     * @param obj       对象，如果static字段，此处为类
     * @param fieldName 字段名
     * @return 字段值
     * @throws UtilException 包装IllegalAccessException异常
     */
    public static Object getFieldValue(Object obj, String fieldName) {
        if (null == obj || !StringUtils.hasText(fieldName)) {
            return null;
        }
        Field field = getField(obj, fieldName);
        try {
            field.setAccessible(true);
            return field.get(obj);
        } catch (Exception e) {
            return null;
        }
    }

    private static Field getField(Object obj, String fieldName) {
        Class<?> aClass = obj.getClass();
        Field[] fields = aClass.getDeclaredFields();
        return Arrays.stream(fields).filter(n -> n.getName().equals(fieldName)).findFirst().orElseGet(() -> {
            Class<?> superclass = aClass.getSuperclass();
            Field[] declaredFields = superclass.getDeclaredFields();
            return Arrays.stream(declaredFields).filter(m -> m.getName().equals(fieldName)).findFirst().orElseThrow(() -> new RuntimeException("找不到字段"));
        });
    }

    /**
     * 获取字段值
     *
     * @param obj   对象，static字段则此字段为null
     * @param field 字段
     * @return 字段值
     * @throws RuntimeException 包装IllegalAccessException异常
     */
    public static Object getFieldValue(Object obj, Field field) {
        if (null == field) {
            return null;
        }
        if (obj instanceof Class) {
            // 静态字段获取时对象为null
            obj = null;
        }
        field.setAccessible(true);
        Object result;
        try {
            result = field.get(obj);
        } catch (IllegalAccessException e) {
            throw new RuntimeException("反射获取对象属性的值异常");
        }
        return result;
    }

    /**
     * 设置字段值<br>
     * 若值类型与字段类型不一致，则会尝试通过 {@link Convert} 进行转换<br>
     * 若字段类型是原始类型而传入的值是 null，则会将字段设置为对应原始类型的默认值（见 {@link ClassUtil#getDefaultValue(Class)}）
     *
     * @param obj       对象,static字段则此处传Class
     * @param fieldName 字段名
     * @param value     值，当值类型与字段类型不匹配时，会尝试转换
     */
    public static void setFieldValue(Object obj, String fieldName, Object value) {
        try {
            Field declaredField = obj.getClass().getDeclaredField(fieldName);
            setFieldValue(obj, declaredField, value);
            System.out.println(declaredField);
        } catch (Exception e) {

        }
        Assert.notNull(obj);
        Assert.notNull(fieldName);

//        final Field field = getField((obj instanceof Class) ? (Class<?>) obj : obj.getClass(), fieldName);
//        setFieldValue(obj, field, value);
    }

    public static void setFieldValue(Object obj, Field field, Object value) {
        field.setAccessible(true);
        try {
            field.set(obj, value);
        } catch (Exception e) {

        }
    }
//    public static void setFieldValue(Object obj, Field field, Object value)  {
//        final Class<?> fieldType = field.getType();
//        if (null != value) {
//            if (false == fieldType.isAssignableFrom(value.getClass())) {
//                //对于类型不同的字段，尝试转换，转换失败则使用原对象类型
//                final Object targetValue = Convert.convert(fieldType, value);
//                if (null != targetValue) {
//                    value = targetValue;
//                }
//            }
//        } else {
//            // 获取null对应默认值，防止原始类型造成空指针问题
//            value = ClassUtil.getDefaultValue(fieldType);
//        }
//
//        setAccessible(field);
//        try {
//            field.set(obj instanceof Class ? null : obj, value);
//        } catch (IllegalAccessException e) {
//            throw new UtilException(e, "IllegalAccess for {}.{}", obj, field.getName());
//        }
//    }

}
